package cn.iocoder.yudao.framework.business.audit.service;

import cn.iocoder.yudao.framework.business.audit.contract.AuditSetter;
import cn.iocoder.yudao.framework.business.audit.enums.AuditStatusEnum;
import cn.iocoder.yudao.framework.business.audit.pojo.form.AuditQueryDTO;
import cn.iocoder.yudao.framework.business.audit.pojo.form.AuditSaveDTO;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.service.impl.BaseService;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.constant.ErrorCodeConstants;
import cn.iocoder.yudao.framework.util.TransactionUtils;
import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  这里是文件说明
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/02/11
 */
@Slf4j
public abstract class AuditBaseService<DO extends AuditSetter, RESP extends AuditSetter, QUERY extends AuditQueryDTO> extends BaseService<DO, RESP, QUERY> implements AuditService {

    @Nonnull
    @Override
    protected CoreQueryWrapper<DO> buildQueryWrapper(QUERY param) {
        CoreQueryWrapper<DO> wrapper = super.buildQueryWrapper(param);
        if (param == null) {
            return wrapper;
        }
        wrapper.eqIfPresent("audit_status", param.getAuditStatus());
        return wrapper;
    }

    @Override
    public boolean updateAudit(AuditSaveDTO param) {
        if (Objects.equals(param.getAuditStatus(), AuditStatusEnum.WAIT.getValue())) {
            // 默认就是待审核状态，不允许从其他状态流转回来
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUDIT_STATUS_DENIED_FOR_WAIT);
        }
        // 校验存在
        DO aDo = getInjectedMapper().selectById(param.getId());
        if (aDo == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUDIT_EXISTS);
        }
        // 更新
        aDo.setAuditStatus(param.getAuditStatus());
        if (Objects.equals(param.getAuditStatus(), AuditStatusEnum.PASS.getValue())) {
            aDo.setAuditNote("");
        } else {
            aDo.setAuditNote(param.getAuditNote());
        }
        aDo.setAuditTime(LocalDateTime.now());
        TransactionUtils.transactional(() -> {
            getInjectedMapper().updateById(aDo);
            if (Objects.equals(param.getAuditStatus(), AuditStatusEnum.REJECT.getValue())) {
                onAuditReject(aDo);
            } else if (Objects.equals(param.getAuditStatus(), AuditStatusEnum.PASS.getValue())) {
                onAuditPass(aDo);
            }
            return null;
        });
        return true;
    }

    protected void onAuditReject(@SuppressWarnings("unused") DO entity) {
        log.debug("onAuditReject: {}", entity);
    }

    protected void onAuditPass(@SuppressWarnings("unused") DO entity) {
        log.debug("onAuditPass: {}", entity);
    }

}
